﻿using ExchangeClient.Abstractions.Model;
using ExchangeClient.Abstractions;
using SyncService.Abstractions.Services;
using System;
using System.Collections.Generic;
using System.Composition;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SyncService.Core.Model;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Runtime.InteropServices;
using SyncService.Common;
using NPOI.XSSF.UserModel;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using HKH.Common;
using Microsoft.VisualBasic;
using NPOI.HPSF;

namespace SyncService.Core.Services
{


    [Export(typeof(ISyncService))]
    [ExportMetadata(YdConstants.ID, "AssetCopy")]
    public class AssetCopyService : SyncServiceBase
    {
        protected override string NotifyGroupName => "";
        private ILogger<AssetService> _logger = null;

        private bool IsNotPush = false;
        public AssetCopyService() : base(YdConstants.YIDEA, "mysqlcache", "")
        {
        }
        protected override void InitializeContext()
        {
            base.InitializeContext();
            _logger = Resolver.Resolve<ILogger<AssetService>>();
        }
        public override void Execute(dynamic? state)
        {
            var financialCodeField = ExtendFields.FirstOrDefault(x => x.ObjectType == 0 && x.Name.Equals("财务资产编码"));
            var companyCodeField = ExtendFields.FirstOrDefault(x => x.ObjectType == 0 && x.Name.Equals("公司代码"));
            var originalValueField = ExtendFields.FirstOrDefault(x => x.ObjectType == 0 && x.Name.Equals("资产原值"));
            var lJZJField = ExtendFields.FirstOrDefault(x => x.ObjectType == 0 && x.Name.Equals("累计折旧"));

            var capitalizationDateField = ExtendFields.FirstOrDefault(x => x.ObjectType == 0 && x.Name.Equals("本金化日期"));
            var scrapDateField = ExtendFields.FirstOrDefault(x => x.ObjectType == 0 && x.Name.Equals("报废日期"));

            var centerCodeField = ExtendFields.FirstOrDefault(x => x.ObjectType == 0 && x.Name.Equals("成本中心码"));
            var zJDateField = ExtendFields.FirstOrDefault(x => x.ObjectType == 0 && x.Name.Equals("折旧开始日"));
            var useYearField = ExtendFields.FirstOrDefault(x => x.ObjectType == 0 && x.Name.Equals("使用年"));
            var useMonthField = ExtendFields.FirstOrDefault(x => x.ObjectType == 0 && x.Name.Equals("使用月"));
            var zJCodeField = ExtendFields.FirstOrDefault(x => x.ObjectType == 0 && x.Name.Equals("折旧码"));

            var companyNameField = ExtendFields.First(x => x.ObjectType == 0 && x.Name == "公司名");
            var centerNameField = ExtendFields.First(x => x.ObjectType == 0 && x.Name == "成本中心名");

            var assetComapnyField = ExtendFields.FirstOrDefault(x => x.ObjectType == 0 && x.Name.Equals("公司名称"));
            var assetCenterField = ExtendFields.FirstOrDefault(x => x.ObjectType == 0 && x.Name.Equals("成本中心名称"));

            var assetAmountField = ExtendFields.FirstOrDefault(x => x.ObjectType == 0 && x.Name.Equals("资产净值"));
            var periodsNumField = ExtendFields.FirstOrDefault(x => x.ObjectType == 0 && x.Name.Equals("已提期数"));

            var companyMasterCodeField = ExtendFields.First(x => x.ObjectType == 51 && x.Name == "公司代码");
            var companyMasterNameField = ExtendFields.First(x => x.ObjectType == 51 && x.Name == "公司名称");

            var centerMasterCodeField = ExtendFields.First(x => x.ObjectType == 52 && x.Name == "成本中心");
            var centerMasterNameField = ExtendFields.First(x => x.ObjectType == 52 && x.Name == "成本中心名称");

            UserDefine userDefine = UserDefines.First(x => x.Name == "资产主数据");
            var company = UserDefines.First(x => x.Name == "公司主数据");
            var center = UserDefines.First(x => x.Name == "成本中心");
            var involvedCodeField = ExtendFields.First(x => x.ObjectType == 0 && x.Name == "发票号码");
            try
            {
                _logger.LogInformation("开始处理批量资产数据");
                RequestData requestData = state;
                List<AssetMaster> data = JsonSerializer.Deserialize<List<AssetMaster>>(requestData.Body);
                _logger.LogInformation("资产数量：" + data.Count);

                Asset asset = new Asset();
                asset.ExtraData = new JsonObject
                {
                    ["AssetMaster"] = requestData.Body
                };
                JsonObject result= ToClient.AddAsset(asset);//插入sap资产表
                if (result["IsComplete"].ToString()=="true")//最后一次推送
                {
                    var synchronousTime = DateTime.Now.ToString("yyyy-MM-dd");
                    //ToClient.AddNewCustomizedFormData(new CustomizedFormData()); //放入对比表
                    //放入对比表差异数据
                    #region 放入自定义表单

                    //JsonObject compareResult = ToClient.GetData(new JsonObject { ["Flag"] = 1 });
                    //if (compareResult["assetArray"] != null && compareResult["assetArray"]!.ToString() != "")
                    //{
                    //    List<AssetMaster> compareData = JsonSerializer.Deserialize<List<AssetMaster>>(compareResult["assetArray"]!.ToString())!;
                    //    int notexits = 0;
                    //    List<AssetMaster> notExitsAsset = new List<AssetMaster>();
                    //    for (int i = 0; i < compareData.Count; i++)
                    //    {
                    //        notexits++;
                    //        notExitsAsset.Add(compareData[i]);
                    //        if (notexits == 100)
                    //        {
                    //            string content = ExportToString(notExitsAsset);
                    //            JsonObject result = YideaClient.FormImport(userDefine.Id, content, 0);
                    //            _logger.LogInformation("返回结果");
                    //            _logger.LogInformation(JsonSerializer.Serialize(result));
                    //            notexits = 0;
                    //            notExitsAsset.Clear();
                    //        }
                    //    }
                    //    if (notExitsAsset.Count > 0)
                    //    {
                    //        _logger.LogInformation("对比数据");
                    //        string content = ExportToString(notExitsAsset);
                    //        JsonObject result = YideaClient.FormImport(userDefine.Id, content, 0);
                    //        _logger.LogInformation("返回结果");
                    //        _logger.LogInformation(JsonSerializer.Serialize(result));
                    //        notExitsAsset.Clear();
                    //    }
                    //}
                    #endregion

                    //更新资产
                    #region 更新资产
                    JsonObject updateResult = ToClient.GetData(new JsonObject { ["Flag"] = 2 });
                    if (updateResult["assetArray"] != null && updateResult["assetArray"]!.ToString() != "")
                    {
                        int sapCount =int.Parse( updateResult["sapCount"].ToString());
                        List< AssetCallBackData> assetCallBackDatas=new List<AssetCallBackData>();
                        List<AssetMaster> updateData = JsonSerializer.Deserialize<List<AssetMaster>>(updateResult["assetArray"]!.ToString())!;
                        int updateCount = updateData.Count;
                        string diffCount = updateResult["diffCount"].ToString();
                        int errorCount=0;
                        foreach (var dataItem in updateData)
                        {
                            var date = DateTime.Now;
                            if (date.Hour >= 20&&date.Hour<23) {
                                _logger.LogInformation("到时间要休息了~");
                                //在八点的时间点，休眠3小时
                                var reciveTime = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd 23:00:00"));
                                TimeSpan timeSpan =reciveTime- DateTime.Now ;
                                int hour = 60 * Convert.ToInt32(Math.Round(timeSpan.TotalMinutes));
                                Thread.Sleep(hour*1000);
                                _logger.LogInformation("休息结束了~");
                            }
                            try
                            {
                                Asset assetInfo = YideaClient.GetAsset(dataItem.BarCode);
                            _logger.LogInformation("资产主数据更新资产："+dataItem.BarCode);
                            if (assetInfo!=null&&!string.IsNullOrEmpty(assetInfo.DataJson))
                            {
                                assetInfo.Amount =decimal.Parse( dataItem.OriginalValue);
                                JsonObject companyDetail = new JsonObject();
                                List<CustomizedFormData> companyData = YideaClient.GetCustomizedFormDatas(formId: company.Id, new QueryParam()
                                {
                                    FilterString = "[{\"field\":\"" + companyMasterCodeField.FieldId + "\",\"type\":\"input\",\"label\":\"公司代码\",\"opt\":\"Equal\",\"val\":\"" + dataItem.CompanyCode + "\"}]"
                                }).ToList();
                                string companyName = "";
                                if (companyData.Count > 0)
                                {
                                    companyDetail = JsonNode.Parse(JsonSerializer.Serialize(companyData[0].Data)).AsObject();
                                    JsonObject companyDataJson = JsonNode.Parse(companyData[0].Data["dataJson"].ToString()).AsObject();
                                    companyDetail[companyMasterNameField.FieldId] = companyDataJson[companyMasterNameField.FieldId].ToString();
                                    companyName = companyDataJson[companyMasterNameField.FieldId].ToString();
                                    companyDetail.Remove("dataJson");
                                    companyDetail[companyMasterCodeField.FieldId] = dataItem.CompanyCode;
                                }

                                JsonObject centerDetail = new JsonObject();
                                var centerData = YideaClient.GetCustomizedFormDatas(formId: center.Id, new QueryParam()
                                {
                                    FilterString = "[{\"field\":\"" + centerMasterCodeField.FieldId + "\",\"type\":\"input\",\"label\":\"成本中心\",\"opt\":\"Equal\",\"val\":\"" + dataItem.CenterCode + "\"}]"
                                }).ToList();
                                string centerName = "";
                                if (centerData.Count > 0)
                                {
                                    centerDetail = JsonNode.Parse(JsonSerializer.Serialize(centerData[0].Data)).AsObject();
                                    JsonObject centerDataJson = JsonNode.Parse(centerData[0].Data["dataJson"].ToString()).AsObject();
                                    centerDetail[centerMasterNameField.FieldId] = centerDataJson[centerMasterNameField.FieldId].ToString();
                                    centerName = centerDataJson[centerMasterNameField.FieldId].ToString();
                                    centerDetail.Remove("dataJson");
                                    centerDetail[centerMasterCodeField.FieldId] = dataItem.CenterCode;
                                }
                                var datajsonNew = assetInfo.DataJson;

                                var index = datajsonNew.IndexOf(involvedCodeField.FieldId);
                                var lasetindex = datajsonNew.LastIndexOf(involvedCodeField.FieldId);
                                if (index != lasetindex)
                                {
                                    datajsonNew = datajsonNew.Substring(0, index) + datajsonNew.Substring(lasetindex, datajsonNew.Length - lasetindex);
                                }
                                var dataJson = JsonNode.Parse(datajsonNew)!.AsObject();

                                dataJson.SetValue(financialCodeField!, dataItem.FinancialCode);

                                dataJson.SetValue(companyCodeField!, dataItem.CompanyCode);

                                dataJson[lJZJField.FieldId] = dataItem.LJZJ;


                                dataJson.SetValue(originalValueField!, dataItem.OriginalValue);

                                dataJson[capitalizationDateField.FieldId] = dataItem.CapitalizationDate;

                                dataJson[scrapDateField.FieldId] = dataItem.ScrapDate;
                                dataJson.SetValue(centerCodeField!, dataItem.CenterCode);
                                dataJson.SetValue(zJDateField!, dataItem.ZJDate);

                                dataJson.SetValue(useYearField!, dataItem.UseYear);
                                dataJson.SetValue(useMonthField!, dataItem.UseMonth);
                                dataJson.SetValue(zJCodeField!, dataItem.ZJCode);

                                dataJson[assetAmountField.FieldId] = (decimal.Parse(dataItem.OriginalValue) + decimal.Parse(dataItem.LJZJ));
                                dataJson[periodsNumField.FieldId] = dataItem.NumBeRaised; //DifferMonth(dataItem.ZJDate);

                                dataJson[companyNameField.FieldId] = companyName;
                                dataJson[centerNameField.FieldId] = centerName;
                                dataJson[assetComapnyField.FieldId] = companyDetail;
                                dataJson[assetCenterField.FieldId] = centerDetail;
                                assetInfo.DataJson = JsonSerializer.Serialize(dataJson);
                                
                                    bool updateAssetFlag = YideaClient.UpdateAsset(assetInfo, assetInfo);
                                    var resultMsg = "成功";
                                    if (!string.IsNullOrEmpty(assetInfo.ErrorMessage)) {
                                        errorCount++;
                                        resultMsg = assetInfo.ErrorMessage;
                                        assetCallBackDatas.Add(new AssetCallBackData()
                                        {
                                            Date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                                            BarCode = dataItem.BarCode,
                                            FinancialCode = dataItem.FinancialCode,
                                            Msg = resultMsg
                                        });
                                    }
                                    
                                    if (!updateAssetFlag) {
                                        _logger.LogError("sap更新资产失败："+ dataItem.BarCode);
                                    }
                                    
                                }
                               
                            }
                            catch (Exception ex)
                            {
                                _logger.LogError(ex, "批量处理资产更新--发生异常");
                                errorCount++;
                                assetCallBackDatas.Add(new AssetCallBackData()
                                {
                                    Date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                                    BarCode = dataItem.BarCode,
                                    FinancialCode=dataItem.FinancialCode,
                                    Msg = ex.ToString()
                                });
                            }
                        }
                        string exportFile = "";
                        if (assetCallBackDatas.Count > 0)
                        {
                            exportFile=ExportToString(assetCallBackDatas);
                        }
                        var domainNameField = ExtendFields.First(e => e.Name == "域名" && e.ObjectType == 0);
                        string fullFile = exportFile == "" ? "" : domainNameField.FieldId + exportFile;
                        WriteToForm(synchronousTime, sapCount, diffCount, updateCount, errorCount, fullFile);

                    }
                    #endregion

                }
                _logger.LogInformation("结束处理批量资产数据");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "批量处理资产发生异常");
            }
        
        }
        private void WriteToForm(string syncTime, int sapCount, string diffCount, int updateCount, int errorCount,string fileName) {
            var tjFormField = UserDefines.First(e => e.Name == "同步资产结果统计" );
           
            var tjDateField = ExtendFields.First(e => e.Name == "同步日期" && e.ObjectType == 56);
            var sapCountField = ExtendFields.First(e => e.Name == "sap资产数" && e.ObjectType == 56);
            var diffCountField = ExtendFields.First(e => e.Name == "差异数量" && e.ObjectType == 56);
            var updateCountField = ExtendFields.First(e => e.Name == "更新数量" && e.ObjectType == 56);
            var errorCountField = ExtendFields.First(e => e.Name == "失败数量" && e.ObjectType == 56);
            var fileLinkField = ExtendFields.First(e => e.Name == "明细地址" && e.ObjectType == 56);
            CustomizedFormData tjForm = new CustomizedFormData();
            tjForm.StartWorkflow = false;
            tjForm.TriggerRobot = false;
            tjForm.FormId = tjFormField.Id;
            tjForm.Data = new JsonObject
            {
                [tjDateField.FieldId] = new JsonObject
                {
                    ["value"] = syncTime
                },
                [sapCountField.FieldId] = new JsonObject
                {
                    ["value"] = sapCount
                },
                [diffCountField.FieldId] = new JsonObject
                {
                    ["value"] = diffCount
                },
                [updateCountField.FieldId] = new JsonObject
                {
                    ["value"] = updateCount
                },
                [errorCountField.FieldId] = new JsonObject
                {
                    ["value"] = errorCount
                },
                [fileLinkField.FieldId] = new JsonObject
                {
                    ["value"] = fileName
                }
            };
            bool addResult = YideaClient.AddNewCustomizedFormData(tjForm);

        }
        private int DifferMonth(string date) { 
        var predate=DateTime.Parse(date);
            var months = ((DateTime.Now.Year - predate.Year) * 12) + DateTime.Now.Month - predate.Month;
            return months;
        }
        public string ExportToString(List<AssetCallBackData> assetExportViewModels)
        {
            _logger.LogInformation("开始导出资产回写情况统计excel~");
            var template = Path.Combine(SyncService.Common.Constants.WebRootPath, "Templates", "资产回写情况统计.xlsx");
            var fileName = DateTime.Now.ToString("yyyyMMddHHmmssffff");
            var target = Path.Combine(SyncService.Common.Constants.WebRootPath, "temp", $"{fileName}资产回写情况统计.xlsx");

            System.IO.File.Copy(template, target);
            FileStream file = new FileStream(target, FileMode.Open, FileAccess.Read);
            var workbook = new XSSFWorkbook(file);
            var sheet = workbook.GetSheet("资产回写情况统计");
            int rowIndex = sheet.LastRowNum + 1;

            foreach (var item in assetExportViewModels)
            {
                
                XSSFRow dataRow = (XSSFRow)sheet.CreateRow(rowIndex);
                dataRow.CreateCell(0).SetCellValue(item.Date);
                dataRow.CreateCell(1).SetCellValue(item.BarCode);
                dataRow.CreateCell(2).SetCellValue(item.FinancialCode);
                dataRow.CreateCell(3).SetCellValue(item.Msg);
                ++rowIndex;
            }

            using (var stream = new FileStream(target, FileMode.Create, FileAccess.Write))
            {
                workbook.Write(stream);
            }
            _logger.LogInformation("生成excel");
            _logger.LogInformation(target);
            //string base64 = FileToBase64String.FileToBase64(target);
            return "/temp/"+ fileName+ "资产回写情况统计.xlsx";
        }
        

    }
}
